<?php

namespace albert\traits;

use app\model\BaseModel;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;

/**
 * Trait ModelTrait
 * @package albert\traits
 */
trait ModelTrait
{
    /**
     * 获取单个数据
     * Author: Albert3306
     * Date: 2020/12/3
     * @param $where
     * @return array|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function get($where)
    {
        if (!is_array($where)) {
            return self::find($where);
        } else {
            return self::where($where)->find();
        }
    }

    /**
     * 获取所有数据
     * Author: Albert3306
     * Date: 2020/12/3
     * @param $function
     * @return Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function all($function): Collection
    {
        $query = self::newQuery();
        $function($query);
        return $query->select();
    }

    /**
     * 分页
     * @param null $model 模型
     * @param null $eachFn 处理结果函数
     * @param array $params 分页参数
     * @param int $limit 分页数
     * @return BaseModel|ModelTrait|array
     * @throws DbException
     */
    public static function page($model = null, $eachFn = null, array $params = [], int $limit = 20)
    {
        if (is_numeric($eachFn) && is_numeric($model)) {
            return parent::page($model, $eachFn);
        }

        if (is_numeric($eachFn)) {
            $limit = $eachFn;
            $eachFn = null;
        } else if (is_array($eachFn)) {
            $params = $eachFn;
            $eachFn = null;
        }

        if (is_callable($model)) {
            $eachFn = $model;
            $model = null;
        } elseif (is_numeric($model)) {
            $limit = $model;
            $model = null;
        } elseif (is_array($model)) {
            $params = $model;
            $model = null;
        }

        if (is_numeric($params)) {
            $limit = $params;
            $params = [];
        }
        $listRows = [
            'list_rows' => $limit,
            'query' => $params
        ];
        $paginate = $model === null ? self::paginate($listRows, false) : $model->paginate($listRows, false);
        $list = is_callable($eachFn) ? $paginate->each($eachFn) : $paginate;
        $page = $list->render();
        $total = $list->total();
        return compact('list', 'page', 'total');
    }

    /**
     * 字符串拼接
     * @param int|array $id
     * @param string $str
     * @return string
     */
    private static function get_field($id, string $str = '|')
    {
        if (is_array($id)) {
            $sql = "";
            $i = 0;
            foreach ($id as $val) {
                $i++;
                if ($i < count($id)) {
                    $sql .= $val . $str;
                } else {
                    $sql .= $val;
                }
            }
            return $sql;
        } else {
            return $id;
        }
    }

    /**
     * 高精度 加法
     * @param $key
     * @param $incField
     * @param $inc
     * @param null $keyField id的字段
     * @param int $acc 精度
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function bcInc($key, $incField, $inc, $keyField = null, int $acc = 2): bool
    {
        if (!is_numeric($inc)) return false;
        $model = new self();
        if ($keyField === null) $keyField = $model->getPk();
        $result = self::where($keyField, $key)->find();
        if (!$result) return false;
        $new = bcadd($result[$incField], $inc, $acc);
        $result->$incField = $new;
        return false !== $result->save();
    }


    /**
     * 高精度 减法
     * @param $key
     * @param string $decField 相减的字段
     * @param float|int $dec 减的值
     * @param null $keyField id的字段
     * @param bool $minus 是否可以为负数
     * @param int $acc 精度
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function bcDec($key, string $decField, $dec, $keyField = null, bool $minus = false, int $acc = 2): bool
    {
        if (!is_numeric($dec)) return false;
        $model = new self();
        if ($keyField === null) $keyField = $model->getPk();
        $result = self::where($keyField, $key)->find();
        if (!$result) return false;
        if (!$minus && $result[$decField] < $dec) return false;
        $new = bcsub($result[$decField], $dec, $acc);
        $result->$decField = $new;
        return false !== $result->save();
    }

    /**
     * 修改一条数据
     * @param $data
     * @param $id
     * @param $field
     * @return bool $type 返回成功失败
     */
    public static function edit($data, $id, $field = null): bool
    {
        $model = new self;
        if (!$field) $field = $model->getPk();
        $res = $model->update($data, [$field => $id]);
        if (isset($res->result))
            return 0 < $res->result;
        else if (isset($res['data']['result']))
            return 0 < $res['data']['result'];
        else
            return false != $res;
    }

    /**
     * 查询一条数据是否存在
     * @param $map
     * @param string $field
     * @return bool 是否存在
     */
    public static function be($map, string $field = ''): bool
    {
        $model = (new self);
        if (!is_array($map) && empty($field)) $field = $model->getPk();
        $map = !is_array($map) ? [$field => $map] : $map;
        return 0 < $model->where($map)->count();
    }

    /**
     * 删除一条数据
     * @param $id
     * @return bool $type 返回成功失败
     */
    public static function del($id): bool
    {
        return false !== self::destroy($id);
    }
}